﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;

namespace VTFC
{
    // ----------------------------------------------------------------------------
    /// <summary>
    /// Main form.
    /// </summary>
    // ----------------------------------------------------------------------------
    public partial class FrmMain : Form
    {
        /// <summary>ListView pointer location coordinate on x-axis.</summary>
        private int lvfile_x;
        /// <summary>ListView pointer location coordinate on y-axis.</summary>
        private int lvfile_y;
        /// <summary>TreeView pointer location coordinate on x-axis.</summary>
        private int tvfolder_x;
        /// <summary>TreeView pointer location coordinate on y-axis.</summary>
        private int tvfolder_y;
        /// <summary>Selected <see cref="VTFC.ListViewItemDocument"/> item.</summary>
        private ListViewItemDocument selecteddocument = null;
        /// <summary>Selected <see cref="VTFC.TreeNodeFolder"/> node.</summary>
        private TreeNodeFolder selectedfolder = null;
        /// <summary></summary>
        private List<string> expandednodes = null;
        
        // ----------------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        // ----------------------------------------------------------------------------
        public FrmMain()
        {
            InitializeComponent();            
            InitializeContent();            
        }//ctor

        private void InitializeContent()
        {
            this.txtRename.BackColor = Constant.VTFC_RENAME_CONTROL_BACKCOLOR;
            this.expandednodes = new List<string>();

            this.Text = String.Format(Resources.MainFormTitle, Constant.VTFC_APPLICATION_FULL_NAME, BaseLogic.GetAssemblyVersion());
            this.miAbout.Text = Resources.FrmMain_MenuItemAbout;
            this.miCheckInDocument.Text = Resources.FrmMain_MenuItemCheckInFile;
            this.miCheckOutDocument.Text = Resources.FrmMain_MenuItemCheckOutFile;
            this.miConfiguration.Text = Resources.FrmMain_MenuItemConfiguration;
            this.miConnect.Text = Resources.FrmMain_MenuItemConnect;
            this.miSaveDocument.Text = Resources.FrmMain_MenuItemSaveAs;
            this.miDeleteDocument.Text = Resources.FrmMain_MenuItemDeleteFile;
            this.miDeleteFolder.Text = Resources.FrmMain_MenuItemDeleteFolder;
            this.miEditDocument.Text = Resources.FrmMain_MenuItemEditFile;
            this.miExit.Text = Resources.FrmMain_MenuItemExit;
            this.miFile.Text = Resources.FrmMain_MenuItemFile;
            this.miGetLatestVersion.Text = Resources.FrmMain_MenuItemGetLatestVersion;
            this.miHelp.Text = Resources.FrmMain_MenuItemHelp;
            this.miNewFolder.Text = Resources.FrmMain_MenuItemNewFolder;
            this.miDisconnect.Text = Resources.FrmMain_MenuItemDisconnect;

            this.gpbOutput.Text = Resources.FrmMain_gpbOutput;

            this.colFileName.Text = Resources.FrmMain_colFileName;
            this.colModified.Text = Resources.FrmMain_colModified;
            this.colModifiedBy.Text = Resources.FrmMain_colModifiedBy;
            this.colSize.Text = Resources.FrmMain_colSize;
            this.colVersion.Text = Resources.FrmMain_colVersion;
        }//func InitializeContent

        private void GetTaskList()
        {
            if (Connector.Server != null)
            {
                bool executed = false;
                using (FrmTaskList frmTaskList = new FrmTaskList())
                {
                    //Output writing
                    frmTaskList.WriteOutput += OnWriteOutputLine;
                    if (frmTaskList.ShowDialog() == DialogResult.OK)
                    {
                        executed = true;
                    }
                    frmTaskList.WriteOutput -= OnWriteOutputLine;
                }
                if (executed)
                {
                    BindContent();
                    WriteOutput(Resources.Msg_Information_ContentUpToDate);
                }
            }
        }//func GetTaskList
                
        private void BindContent()
        {
            BindFileIconList();
            BindListTree();
        }//func BindContent

        private void BindFileIconList()
        {
            int imagecount = imgListFile.Images.Count;
            if (imagecount > Constant.VTFC_IMGLISTFILE_OFFSET)
            {
                //clean image list.
                for (int i = imagecount - 1; i > (Constant.VTFC_IMGLISTFILE_OFFSET-1); i--)
                {
                    imgListFile.Images.RemoveAt(i);
                }
            }

            //add icons from Content
            foreach (Icon icon in Connector.Content.Icons)
            {
                imgListFile.Images.Add(Image.FromStream(new MemoryStream(icon.Image)));
            }
        }//func BindFileIconList

        private void ClearData()
        {            
            tvFolders.Nodes.Clear();
            lvDocuments.Items.Clear();
        }//func ClearData

        private void CollectExpandedNodes(TreeNodeCollection nodes)
        {
            if (nodes != null)
            {
                foreach (TreeNodeFolder node in nodes)
                {
                    if (node.IsExpanded)
                    {
                        expandednodes.Add(node.FolderPath);
                    }
                    //Walk recursive
                    CollectExpandedNodes(node.Nodes);
                }
            }
        }//func CollectExpandedNodes

        private void ExpandNodes(TreeNodeCollection nodes)
        {
            if (nodes != null)
            {
                foreach (TreeNodeFolder node in nodes)
                {
                    if (expandednodes.Contains(node.FolderPath))
                    {
                        node.Expand();
                    }
                    //Walk recursive
                    ExpandNodes(node.Nodes);
                }                
            }
        }//func ExpandNodes

        private void BindListTree()
        {
            expandednodes.Clear();
            CollectExpandedNodes(tvFolders.Nodes);

            ClearData();

            TreeNodeFolder projectnode = new TreeNodeFolder()
            {
                ImageIndex = 0,
                SelectedImageIndex = 0,
                Text = Connector.Server.Name,
                FolderType = FolderType.PROJECT,
            };
            tvFolders.Nodes.Add(projectnode);

            TreeNodeFolder listnode = null;
            foreach (List list in Connector.Content.Lists)
            {
                listnode = new TreeNodeFolder()
                {
                    Text = list.Name,
                    FolderPath = list.Url,
                    ImageIndex = 1,
                    SelectedImageIndex = 1,
                    ListName = list.Name,
                    FolderType = FolderType.LIST,
                };

                projectnode.Nodes.Add(listnode);

                foreach (Folder folder in list.Folders)
                {
                    BindFolderTree(listnode, folder.Directory.Split('\\'), 1);
                }
            }

            projectnode.Expand();

            ExpandNodes(tvFolders.Nodes);
        }//func BindListTree

        private void BindFolderTree(TreeNodeFolder pnode, string[] folderpath, int level)
        {
            TreeNodeFolder foldernode = null;
            string currentfolder = folderpath[level];
            bool deeper = level < folderpath.Length - 1;
            foreach (TreeNodeFolder cnode in pnode.Nodes)
            {
                if (cnode.Text == currentfolder)
                {
                    foldernode = cnode;
                    break;
                }
            }
            if (foldernode != null)
            {
                if (deeper)
                {
                    BindFolderTree(foldernode, folderpath, ++level);
                }
            }
            else
            {
                foldernode = new TreeNodeFolder()
                {
                    Text = currentfolder,
                    FolderPath = GetFolderUrlPart(folderpath, level),
                    ListName = pnode.ListName,
                    ImageIndex = 2,
                    SelectedImageIndex = 3,
                    FolderType = FolderType.FOLDER,
                };
                                
                pnode.Nodes.Add(foldernode);
                if (deeper)
                {
                    BindFolderTree(foldernode, folderpath, ++level);
                }                
            }
        }//func BindFolderTree
               
        private void BindDocumentList(TreeNodeFolder node)
        {
            lvDocuments.Items.Clear();
            if (node.FolderType != FolderType.PROJECT)
            {
                List<Document> documents = Connector.Content.GetFilesByDirectoryPath(node.FolderPath);
                List<string> files = new List<string>();
                ListViewItemDocument item = null;
                foreach (Document document in documents)
                {
                    item = new ListViewItemDocument()
                    {
                        ImageIndex = document.IsCheckedOut ? 0 : Connector.Content.GetIconIndex(Path.GetExtension(document.MetaData.FileName).TrimStart('.')),
                        Document = document,
                    };
                    item.SetForeColor();
                    lvDocuments.Items.Add(item);
                    files.Add(document.MetaData.FileName);
                }

                if (Connector.Server.ShowUnControlledFiles)
                {
                    string directorypath = Connector.GetAbsoluteFolderPath(node.FolderPath);
                    if (Directory.Exists(directorypath))
                    {
                        string filename = null;
                        FileInfo info = null;

                        List<string> locals = Directory.GetFiles(directorypath).ToList();
                        foreach (string local in locals)
                        {
                            filename = Path.GetFileName(local);
                            if (!files.Contains(filename))
                            {
                                info = BaseLogic.GetFileInfo(local);
                                item = new ListViewItemDocument();
                                item.ImageIndex = Connector.Content.GetIconIndex(Path.GetExtension(filename).TrimStart('.'));
                                item.SubItems.Add(filename);
                                item.SubItems.Add(info.LastWriteTime.ToString(Resources.DateTimeFormater));
                                item.SubItems.Add("N/A");
                                item.SubItems.Add("N/A");
                                item.SubItems.Add(BaseLogic.GetSizeDisplay(info.Length));
                                item.SetForeColor();
                                lvDocuments.Items.Add(item);
                            }
                        }
                    }

                    //Items should resort.
                    lvDocuments.ListViewItemSorter = new ListViewItemSorter(colFileName.DisplayIndex, SortOrder.Ascending);
                    lvDocuments.Sort();
                }
            }
        }//func BindDocumentList

        private string GetFolderUrlPart(string[] folderparts, int level)
        {
            string folderUrl = "";
            for (int i = 0; i < level + 1; i++)
            {
                folderUrl += folderparts[i] + "\\";
            }
            return folderUrl.TrimEnd('\\');
        }//func GetFolderUrlPart

        private bool IsMultiSelected
        {
            get { return lvDocuments.SelectedItems.Count > 1; }
        }//prop IsMultiSelected
               
        private bool CanCheckIn
        {
            get
            {
                bool checkin = true;
                List<Document> documents = GetSelectedDocuments();
                foreach (Document document in documents)
                {
                    if (!document.IsCheckedOut || document.CheckedOutUserID != Connector.UserID )
                    {
                        checkin = false;
                        break;
                    }
                }
                return checkin;
            }
        }//prop CanCheckIn

        private bool NoneCheckedOut
        {
            get
            {
                bool ncout = true;
                List<Document> documents = GetSelectedDocuments();
                foreach (Document document in documents)
                {
                    if (document.IsCheckedOut)
                    {
                        ncout = false;
                        break;
                    }
                }
                return ncout;
            }
        }//prop NoneCheckedOut

        private List<Document> GetSelectedDocuments()
        {
            List<ListViewItemDocument> items = null;
            return GetSelectedDocuments(out items);
        }//func GetSelectedDocuments

        private List<Document> GetSelectedDocuments(out  List<ListViewItemDocument> items)
        {
            List<Document> documents = new List<Document>();
            items = GetSelectedItems();
            foreach (ListViewItemDocument item in items)
            {
                if (item.Document != null)
                {
                    documents.Add(item.Document);
                }
            }
            return documents;
        }//func GetSelectedDocuments

        private List<ListViewItemDocument> GetSelectedItems()
        {
            List<ListViewItemDocument> items = new List<ListViewItemDocument>();
            foreach (ListViewItemDocument item in lvDocuments.SelectedItems)
            {
                items.Add(item);
            }
            return items;
        }//func GetSelectedItems

        #region Control events
                                
        private void lvDocuments_DoubleClick(object sender, EventArgs e)
        {
            selecteddocument = lvDocuments.GetItemAt(lvfile_x, lvfile_y) as ListViewItemDocument;
            if (selecteddocument != null )
            {
                EditDocument();
            }
        }//func lvDocuments_DoubleClick

        private void lvDocuments_MouseMove(object sender, MouseEventArgs e)
        {
            lvfile_x = e.X;
            lvfile_y = e.Y;
        }//func lvDocuments_MouseMove

        private void lvDocuments_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Delete:
                    DeleteDocument();
                    break;
                case Keys.Enter:
                    EditDocument();
                    break;
            }
        }//func lvDocuments_KeyDown

        private void lvDocuments_SizeChanged(object sender, EventArgs e)
        {
            int x = lvDocuments.Size.Width;
            if (x > Constant.VTFC_DOCUMENTLIST_DEFAULT_WIDTH)
            {
                colFileName.Width = (x - Constant.VTFC_DOCUMENTLIST_FILENAME_OFFSET);
            }
        }//func lvDocuments_SizeChanged
                
        private void tvFolders_AfterSelect(object sender, TreeViewEventArgs e)
        {
            selectedfolder = e.Node as TreeNodeFolder;
            if (selectedfolder != null)
            {
                selectedfolder.Expand();
                BindDocumentList(selectedfolder);
            }
        }//func tvFolders_AfterSelect

        private void tvFolders_MouseMove(object sender, MouseEventArgs e)
        {
            tvfolder_x = e.X;
            tvfolder_y = e.Y;
        }//func tvFolders_MouseMove

        private void tvFolders_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Delete:
                    DeleteFolder();
                    break;
            }
        }//func tvFolders_KeyDown
               
        private void txtRename_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Enter:
                    string name = txtRename.Text;
                    if (BaseLogic.ValidateFileName(name))
                    {
                        HideRenameControl();
                        RenameDocument(name);
                    }
                    else
                    {
                        BaseLogic.ShowWarrning(Resources.Msg_Warrning_RenameDocument);
                    }                    
                    break;
                case Keys.Escape:
                    HideRenameControl();
                    break;
            }
        }//func txtRename_KeyDown

        private void FrmMain_SizeChanged(object sender, EventArgs e)
        {
            HideRenameControl();
        }//func FrmMain_SizeChanged

        private void FrmMain_Load(object sender, EventArgs e)
        {
            //Started with Content.tfc?
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length > 1)
            {
                ConnectToServer(Connector.GetContentServerUrl(args[1]));
            }
            else
            {
                if (ConfigManager.GetBoolean(Constant.VTFC_CONFIGURATION_AUTOCONNECT))
                {
                    ConnectToServer(ServerManager.ServerContainer.DefaultServerUrl);
                }
                else
                {
                    miConnect.Enabled = true;
                }
            }
        }//func FrmMain_Load
                
        #endregion

        #region Event functions

        private void Connect()
        {
            bool connect = false;
            using (FrmServerList frmServerList = new FrmServerList())
            {
                if (frmServerList.ShowDialog() == DialogResult.OK)
                {
                    connect = true;
                }
            }
            if (connect)
            {
                ConnectToServer(ServerManager.ServerContainer.DefaultServerUrl);
            }   
        }//func Connect

        private void GetLatestVersion()
        {
            if (Connector.Connected)
            {
                GetTaskList();
            }
        }//func GetLatestVersion

        private void Disconnect()
        {
            Connector.SaveContent();

            miGetLatestVersion.Enabled = false;
            miDisconnect.Enabled = false;

            ClearData();

            WriteOutput(String.Format(Resources.Msg_Information_Disconnect, Connector.Server.Name));
        }//func Disconnect

        private void Exit()
        {
            this.Dispose();
        }//func Exit

        private void About()
        {
            using (FrmAbout about = new FrmAbout())
            {
                about.ShowDialog();
            }
        }//func About

        private void Configuration()
        {
            using (FrmConfig frmConfiguration = new FrmConfig())
            {
                frmConfiguration.ShowDialog();
            }
        }//func Configuration

        private void NewFolder()
        {
            if (selectedfolder != null)
            {
                try
                {
                    string foldername = null;
                    switch (selectedfolder.FolderType)
                    {
                        case FolderType.PROJECT:
                            string description = null;
                            bool enableversioning = true;
                            bool quicklaunch = true;
                            using (FrmList frmList = new FrmList())
                            {
                                if (frmList.ShowDialog() == DialogResult.OK)
                                {
                                    foldername = frmList.ListName;
                                    description = frmList.Description;
                                    enableversioning = frmList.EnableVersioning;
                                    quicklaunch = frmList.QuickLaunch;
                                }
                            }
                            if (foldername != null)
                            {
                                Connector.AddNewList(foldername, description, enableversioning, quicklaunch);
                                WriteOutput(String.Format(Resources.Msg_Information_NewList, foldername));
                            }
                            break;
                        case FolderType.LIST:
                        case FolderType.FOLDER:
                            string folderpath = "";
                            using (FrmFolder frmNewList = new FrmFolder())
                            {
                                if (frmNewList.ShowDialog() == DialogResult.OK)
                                {
                                    foldername = frmNewList.FolderName;
                                }
                            }
                            if (foldername != null)
                            {
                                folderpath = selectedfolder.FolderPath + "\\" + foldername;
                                Connector.AddNewFolder(selectedfolder.ListName, folderpath);
                                WriteOutput(String.Format(Resources.Msg_Information_NewFolder, folderpath));
                            }
                            break;
                    }
                    if (foldername != null)
                    {
                        BindContent();
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
        }//func NewFolder

        private void AddItems()
        {
            if (selectedfolder != null)
            {
                try
                {
                    string folderpath = BaseLogic.SelectFolder(Connector.Server.WorkDircetory);
                    if (folderpath != null)
                    {
                        Connector.AddItems(folderpath, selectedfolder.ListName, selectedfolder.FolderType, selectedfolder.FolderPath);
                        WriteOutput(String.Format(Resources.Msg_Information_AddItems, folderpath));
                        
                        BindContent();
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
        }//func AddItems

        private void DeleteFolder()
        {
            if (selectedfolder != null)
            {
                try
                {
                    if (BaseLogic.ShowQuerstion(String.Format(Resources.Msg_Question_DeleteFolder, selectedfolder.FolderPath)))
                    {
                        string directorypath = Path.Combine(Connector.Server.WorkDircetory, selectedfolder.FolderPath);
                        switch (selectedfolder.FolderType)
                        {
                            case FolderType.LIST:
                                Connector.DeleteList(selectedfolder.ListName);
                                break;
                            case FolderType.FOLDER:
                                Connector.DeleteFolder(selectedfolder.FolderPath);
                                break;
                        }

                        WriteOutput(String.Format(Resources.Msg_Information_DeleteFolder, selectedfolder.FolderPath));

                        //Update TreeView content
                        TreeNodeFolder parentnode = selectedfolder.Parent as TreeNodeFolder;
                        parentnode.Nodes.Remove(selectedfolder);
                        selectedfolder = null;

                        if (BaseLogic.ShowQuerstion(String.Format(Resources.Msg_Question_DeleteLocalDirectory, directorypath)))
                        {
                            BaseLogic.DeleteDirectory(directorypath);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
        }//func DeleteFolder

        private void UploadDocument()
        {
            if (selectedfolder != null)
            {
                try
                {
                    string defaultdirectory = Path.Combine(Connector.Server.WorkDircetory, selectedfolder.FolderPath);

                    List<string> documents = BaseLogic.OpenFiles(defaultdirectory, null);
                    if (documents != null)
                    {
                        Connector.AddNewDocument(selectedfolder.ListName, selectedfolder.FolderPath, documents);
                        foreach (string filepath in documents)
                        {
                            WriteOutput(String.Format(Resources.Msg_Information_UploadFile, filepath, selectedfolder.FolderPath));
                        }
                        //Update file list.
                        BindFileIconList();//refresh icons.
                        BindDocumentList(selectedfolder);
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
        }//func UploadDocument

        private void EditDocument()
        {
            List<ListViewItemDocument> items = GetSelectedItems();
            if (items.Count > 0)
            {
                foreach (ListViewItemDocument item in items)
                {
                    try
                    {
                        if (item.Document != null)
                        {
                            BaseLogic.StartProcess(Connector.GetAbsoluteDocumentPath(item.Document.MetaData));
                            WriteOutput(String.Format(Resources.Msg_Information_EditDocument, Connector.GetRelativeFilePath(item.Document.MetaData)));
                        }
                        else
                        {
                            string filepath = Path.Combine(Connector.GetAbsoluteFolderPath(selectedfolder.FolderPath), item.SubItems[1].Text);
                            if (File.Exists(filepath))
                            {
                                BaseLogic.StartProcess(filepath);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogEvent(ex);
                        BaseLogic.ShowError(ex);
                    }
                }
            }
        }//func EditDocument

        private void SaveDocument()
        {
            List<Document> documents = GetSelectedDocuments();
            if (documents.Count > 0)
            {
                if (documents.Count == 1)
                {
                    string filepath = BaseLogic.SaveFile(Connector.GetAbsoluteFolderPath(selectedfolder.FolderPath), documents[0].MetaData.FileName);
                    if (filepath != null)
                    {
                        BaseLogic.CopyRenamedFile(Connector.GetAbsoluteDocumentPath(documents[0].MetaData), filepath, true);
                        WriteOutput(String.Format(Resources.Msg_Information_SaveDocument, documents[0].MetaData.FileName, Connector.GetAbsoluteFolderPath(selectedfolder.FolderPath)));
                    }
                }
                else
                {
                    string folderpath = BaseLogic.SelectFolder(null);
                    if (folderpath != null)
                    {
                        if (Connector.GetAbsoluteFolderPath(selectedfolder.FolderPath) != folderpath)
                        {
                            string sourcefilepath = null;
                            string targetfilepath = null;
                            bool enablecopy = false;
                            foreach (Document document in documents)
                            {
                                enablecopy = false;
                                sourcefilepath = Connector.GetAbsoluteDocumentPath(document.MetaData);
                                targetfilepath = Path.Combine(folderpath, document.MetaData.FileName);

                                if (File.Exists(targetfilepath))
                                {
                                    DialogResult result = BaseLogic.ShowQuerstion(String.Format(Resources.Msg_Question_OverWriteLocalFile, document.MetaData.FileName), true);
                                    if (result == DialogResult.Cancel)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        if (result == DialogResult.Yes)
                                        {
                                            enablecopy = true;
                                        }
                                    }
                                }
                                else
                                {
                                    enablecopy = true;
                                }
                                if (enablecopy)
                                {
                                    BaseLogic.CopyFile(sourcefilepath, folderpath, true);
                                    WriteOutput(String.Format(Resources.Msg_Information_SaveDocument, document.MetaData.FileName, folderpath));
                                }
                            }
                        }
                    }
                }
                BindDocumentList(selectedfolder);
            }
        }//func SaveDocument

        private void CheckOutDocument()
        {
            List<ListViewItemDocument> items = GetSelectedItems();
            foreach (ListViewItemDocument item in items)
            {
                try
                {
                    bool checkout = true;
                    if (item.Document.Skipped)
                    {
                        checkout = BaseLogic.ShowQuerstion(String.Format(Resources.Msg_Question_SkippedDocument_CheckOut, item.Document.MetaData.FileName));
                    }
                    if (checkout)
                    {
                        Connector.CheckOut(item.Document);
                        WriteOutput(String.Format(Resources.Msg_Information_CheckOut, Connector.GetRelativeFilePath(item.Document.MetaData)));
                        item.Document.IsCheckedOut = true;
                        item.ImageIndex = 0;
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
            BindDocumentList(selectedfolder);
        }//func CheckOutDocument

        private void CheckInDocument()
        {
            List<ListViewItemDocument> items = GetSelectedItems();
            foreach (ListViewItemDocument item in items)
            {
                try
                {
                    Connector.CheckIn(item.Document);
                    WriteOutput(String.Format(Resources.Msg_Information_CheckIn, Connector.GetRelativeFilePath(item.Document.MetaData)));
                    item.Document.IsCheckedOut = false;
                    item.Document.Skipped = false;
                    item.ImageIndex = Connector.Content.GetIconIndex(Path.GetExtension(item.Document.MetaData.FileName).TrimStart('.'));
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
            BindDocumentList(selectedfolder);
        }//func CheckInDocument

        private void UndoPendingChanges()
        {
            List<ListViewItemDocument> items = GetSelectedItems();
            foreach (ListViewItemDocument item in items)
            {
                try
                {
                    Connector.UndoPendingChanges(item.Document);
                    WriteOutput(String.Format(Resources.Msg_Information_Undo, Connector.GetRelativeFilePath(item.Document.MetaData)));
                    item.Document.IsCheckedOut = false;
                    item.ImageIndex = Connector.Content.GetIconIndex(Path.GetExtension(item.Document.MetaData.FileName).TrimStart('.'));
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
            BindDocumentList(selectedfolder);
        }//func UndoPendingChanges

        private void ShowRenameControl()
        {
            int x = 0;
            int y = 0;
            int w = 0;
            string text = "";

            if (selecteddocument != null)
            {
                this.scContent.Panel2.Controls.Add(this.txtRename);
                Rectangle itemrect = lvDocuments.GetItemRect(selecteddocument.Index);
                x = lvDocuments.Columns[0].Width + Constant.VTFC_DOCUMENTLIST_RENAME_OFFSET_X;
                y = itemrect.Location.Y + Constant.VTFC_DOCUMENTLIST_RENAME_OFFSET_Y;
                w = lvDocuments.Columns[1].Width - Constant.VTFC_DOCUMENTLIST_RENAME_OFFSET_X;
                text = selecteddocument.Document.MetaData.FileName;
            
                txtRename.Location = new Point(x, y);
                txtRename.Width = w;
                txtRename.Text = text;
                txtRename.BringToFront();
                txtRename.Focus();
                txtRename.LostFocus += txtRenameDocument_LostFocus;
            }
        }//func ShowRenameControl
               
        private void txtRenameDocument_LostFocus(object sender, EventArgs e)
        {
            HideRenameControl();
        }//func txtRenameDocument_LostFocus

        private void HideRenameControl()
        {
            txtRename.Text = "";
            txtRename.LostFocus -= txtRenameDocument_LostFocus;
            txtRename.SendToBack();
        }//func HideRenameControl
        
        private void RenameDocument(string documentname)
        {
            if (selecteddocument != null)
            {
                try
                {
                    string olddocumentname =  selecteddocument.Document.MetaData.FileName;
                    Connector.RenameDocument(selecteddocument.Document, documentname);
                    BaseLogic.RenameFile(Connector.GetAbsoluteDocumentPath(selecteddocument.Document.MetaData), documentname);
                    WriteOutput(String.Format(Resources.Msg_Information_RenameDocument, olddocumentname, documentname));
                    BindDocumentList(selectedfolder);
                }
                catch (Exception ex)
                {
                    Logger.LogEvent(ex);
                    BaseLogic.ShowError(ex);
                }
            }
        }//func RenameDocument
                
        private void DeleteDocument()
        {
            List<ListViewItemDocument> items = GetSelectedItems();
            if (items.Count > 0)
            {
                foreach (ListViewItemDocument item in items)
                {
                    try
                    {
                        bool deletelocal = false;
                        string filepath = null;
                        if (item.Document != null)
                        {
                            filepath = Connector.GetAbsoluteDocumentPath(item.Document.MetaData);
                            if (BaseLogic.ShowQuerstion(String.Format(Resources.Msg_Question_ComfirmDelete, item.Document.MetaData.FileName)))
                            {
                                Connector.DeleteDocument(item.Document);
                                WriteOutput(String.Format(Resources.Msg_Information_DeleteFile, Connector.GetRelativeFilePath(item.Document.MetaData)));
                                deletelocal = true;
                            }
                        }
                        else
                        {
                            filepath = Path.Combine(Connector.GetAbsoluteFolderPath(selectedfolder.FolderPath), item.SubItems[1].Text);
                            deletelocal = true;
                        }
                        if (deletelocal)
                        {
                            if (BaseLogic.ShowQuerstion(String.Format(Resources.Msg_Question_DeleteLocalFile, filepath)))
                            {
                                BaseLogic.DeleteFile(filepath);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogEvent(ex);
                        BaseLogic.ShowError(ex);
                    }
                }
                //Update file ListView.
                BindDocumentList(selectedfolder);
            }
        }//func DeleteDocument

        #endregion

        #region MenuStrip events

        private void miConnect_Click(object sender, EventArgs e)
        {
            Connect();      
        }//func miConnect_Click

        private void miGetLatestVersion_Click(object sender, EventArgs e)
        {
            GetLatestVersion();
        }//func miGetLatestVersion_Click
        
        private void miDisconnect_Click(object sender, EventArgs e)
        {
            Disconnect();
        }//func miDisconnect_Click
                
        private void miExit_Click(object sender, EventArgs e)
        {
            Exit();
        }//func miExit_Click

        private void miAbout_Click(object sender, EventArgs e)
        {
            About();
        }//func miAbout_Click

        private void miConfiguration_Click(object sender, EventArgs e)
        {
            Configuration();
        }//func miConfiguration_Click
        #endregion
                
        #region ContextMenuStrip events

        private void miNewFolder_Click(object sender, EventArgs e)
        {
            NewFolder();
        }//func miNewFolder_Click


        private void miAddItems_Click(object sender, EventArgs e)
        {
            AddItems();
        }//func miAddItems_Click
                       
        private void miDeleteFolder_Click(object sender, EventArgs e)
        {
            DeleteFolder();
        }//func miDeleteFolder_Click

        private void miUploadDocument_Click(object sender, EventArgs e)
        {
            UploadDocument();
        }//func miUploadDocument_Click

        private void miEditDocument_Click(object sender, EventArgs e)
        {
            EditDocument();
        }//func miEditFile_Click

        private void miSaveDocument_Click(object sender, EventArgs e)
        {
            SaveDocument();
        }//func miSaveDocument_Click

        private void miCheckOutDocument_Click(object sender, EventArgs e)
        {
            CheckOutDocument();
        }//func miCheckOutDocument_Click

        private void miCheckInDocument_Click(object sender, EventArgs e)
        {
            CheckInDocument();            
        }//func miCheckInDocument_Click

        private void miUndoDocument_Click(object sender, EventArgs e)
        {
            UndoPendingChanges();
        }//func miUndoDocument_Click
       
        private void miRenameDocument_Click(object sender, EventArgs e)
        {
            ShowRenameControl();
        }//func miRenameDocument_Click
      
        private void miDeleteDocument_Click(object sender, EventArgs e)
        {
            DeleteDocument();
        }//func miDeleteDocument_Click

        private void cmsFolder_Opening(object sender, CancelEventArgs e)
        {
            if (Connector.Connected)
            {
                selectedfolder = tvFolders.GetNodeAt(tvfolder_x, tvfolder_y) as TreeNodeFolder;
                if (selectedfolder != null)
                {
                    miNewFolder.Enabled = true;
                    bool notproject = selectedfolder.FolderType != FolderType.PROJECT;

                    miDeleteFolder.Enabled = notproject;
                }
                else
                {
                    e.Cancel = true;
                }
            }
            else
            {
                e.Cancel = true;
            }
        }//func cmsFolder_Opening

        private void cmsFile_Opening(object sender, CancelEventArgs e)
        {
            if (Connector.Connected)
            {
                selecteddocument = lvDocuments.GetItemAt(lvfile_x, lvfile_y) as ListViewItemDocument;
                if (selecteddocument != null)
                {
                    if (selecteddocument.Document != null)
                    {
                        if (IsMultiSelected)
                        {
                            bool nonecheckedout = NoneCheckedOut;

                            miEditDocument.Enabled = false;
                            miUploadDocument.Enabled = false;
                            miRenameDocument.Enabled = false;
                            miDeleteDocument.Enabled = true;
                            miCheckOutDocument.Enabled = nonecheckedout;
                        }
                        else
                        {
                            miEditDocument.Enabled = true;
                            miUploadDocument.Enabled = true;
                            miDeleteDocument.Enabled = true;

                            if (selecteddocument.Document.IsCheckedOut)
                            {
                                miCheckOutDocument.Enabled = false;
                                miRenameDocument.Enabled = false;
                            }
                            else
                            {
                                miCheckOutDocument.Enabled = true;
                                miRenameDocument.Enabled = true;
                            }
                        }

                        bool canchackin = CanCheckIn;
                        miCheckInDocument.Enabled = canchackin;
                        miUndoDocument.Enabled = canchackin;
                        miSaveDocument.Enabled = true;
                    }
                    else
                    {
                        miEditDocument.Enabled = true;
                        miUploadDocument.Enabled = true;
                        miDeleteDocument.Enabled = true;
                        miCheckOutDocument.Enabled = false;
                        miCheckInDocument.Enabled = false;
                        miUndoDocument.Enabled = false;
                        miRenameDocument.Enabled = false;
                        miSaveDocument.Enabled = false;
                    }
                }
                else
                {
                    miEditDocument.Enabled = false;
                    miUploadDocument.Enabled = true;
                    miDeleteDocument.Enabled = false;
                    miCheckOutDocument.Enabled = false;
                    miCheckInDocument.Enabled = false;
                    miUndoDocument.Enabled = false;
                    miRenameDocument.Enabled = false;
                    miSaveDocument.Enabled = false;
                }
            }
            else
            {
                e.Cancel = true;
            }
        }//func cmsFile_Opening
        #endregion

        #region Writing output

        void OnWriteOutputLine(object sender, WriteOutputEventArgs e)
        {
            WriteOutput(e.Message);
        }//func OnWriteOutputLine

        private void WriteOutput(string message)
        {
            rtbOutput.AppendText(String.Format("{0}: {1}", DateTime.Now.ToString(Resources.DateTimeFormater), message));
            rtbOutput.AppendText("\n");
            rtbOutput.ScrollToCaret();//scroll to end
        }//func WriteOutput
        #endregion

        #region Connect to server
                
        private void ConnectToServer(string serverurl)
        {
            try
            {
                if (!String.IsNullOrEmpty(serverurl))
                {
                    WriteOutput(String.Format(Resources.Msg_Information_TryToConnect, serverurl));
                    bgwConnect.RunWorkerAsync(serverurl); //Run 'bgwConnect_DoWork' method.
                }
            }
            catch (Exception ex)
            {
                Logger.LogEvent(ex);
                BaseLogic.ShowError(ex);
            }
        }//func ConnectToServer

        private void bgwConnect_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                string serverurl = e.Argument.ToString();
                e.Result = serverurl;
                Server server = ServerManager.GetServerByUrl(serverurl);
                if (server != null)
                {
                    Connector.Initialize(server);
                }
            }
            catch (Exception ex)
            {
                Logger.LogEvent(ex);
                BaseLogic.ShowError(ex);
            }            
        }//func bgwConnect_DoWork

        private void bgwConnect_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (Connector.Connected)
            {
                miGetLatestVersion.Enabled = true;
                miDisconnect.Enabled = true;

                WriteOutput(Resources.Msg_Information_Connected);
                
                GetTaskList();
            }
            else
            {
                WriteOutput(String.Format(Resources.Msg_Information_ConnectFailed, e.Result.ToString()));
            }

            miConnect.Enabled = true;
        }//func bgwConnect_RunWorkerCompleted
                                                             
        #endregion

    }//class FrmMain
}//namespace VTFC
